package org.leaf.green.b2b

import org.springframework.transaction.annotation.*
import org.hibernate.FetchMode as FM
import org.hibernate.criterion.CriteriaSpecification
import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod

class StockOutService {

    static transactional = true

    def init(Long distributionId) {
        def stockOutInstance = new StockOut()
            //set serialnumber
            stockOutInstance.serialNumber = "${new Date().format('yyyyMMdd')}000"
            //set approved 
            stockOutInstance.approved = false

        def distributionInstance = Distribution.withCriteria(uniqueResult:true){

            createAlias 'retailer', 'r', CriteriaSpecification.LEFT_JOIN
            
            projections{
                property("r.id")
            }
            
            fetchMode "retailer", FM.JOIN

            eq("id", distributionId)
        }

        //dynamic data binding
        BindDynamicMethod mybind = new BindDynamicMethod()
        def mymap = [
            'retailer.id': distributionInstance,
            'distribution.id' : distributionId
        ]
        def myargs =  [stockOutInstance, mymap]
        mybind.invoke(stockOutInstance, 'bind', (Object[]) myargs)

        //get distribution details
        def distributionDetails = DistributionDetail.withCriteria(){

            createAlias 'product', 'prod', CriteriaSpecification.LEFT_JOIN
            createAlias 'distribution', 'dist', CriteriaSpecification.LEFT_JOIN
        
            projections{
                property("id")
                property("prod.id")
                property("unit")
                property("quantity")
                property("sended")
                property("price")
                property("amount")
            }

            fetchMode "product", FM.JOIN
            fetchMode "distribution", FM.JOIN

            eq("dist.id", distributionId)

            order("serialNumber", "asc")            
        }
         
        def begin_serialNumber = 0
        distributionDetails.each{
            begin_serialNumber += 1
           
            def stockOutDetail = new StockOutDetail(
                  serialNumber : String.format('%03d', begin_serialNumber)
                , distributionDetail : it[0]
                , product : it[1]
                , unit : it[2]
                , quantity : it[3] - it[4]
                , actual : 0
                , price : it[5]
                , amount : it[6]
            )
            def availableInventory = availableInventory(it[1])

            def begin_serialNumber_detail = 0
            availableInventory.each{
                begin_serialNumber_detail += 1
                def stockInOutDetail = new StockInOutDetail(
                      serialNumber : String.format('%03d', begin_serialNumber_detail)
                    , stockInDetail : it
                    , quantity : 0
                )
                stockOutDetail.addToDetails(stockInOutDetail)
            }
            stockOutInstance.addToDetails(stockOutDetail)
        }
        return stockOutInstance
    }

    def availableInventory(Long productId){
        log.info("availableInventory")
        def stockInDetails = StockInDetail.withCriteria(){

            createAlias 'product', 'prod', CriteriaSpecification.LEFT_JOIN
            createAlias 'stockIn', 'master', CriteriaSpecification.LEFT_JOIN

            projections{
                property("id")
                //property("quantity")
                //property("used")
                //property("surplus")
                //property("price")
                //property("amount")
            }
           
            fetchMode "product", FM.JOIN
            fetchMode "stockIn", FM.JOIN

            eq("prod.id", productId)
            eq("master.approved", true)
            eq("isOver", false)

            order("life", "asc")
        }
        return stockInDetails
    }
}
